import {
  mergeObj,
  isArray,
  xssValueFilter,
  isObject,
  objHas,
  isNum,
  getCssStyle,
} from '@/utils/util';
import { $demoi18n } from '@/utils/lang';
import echartUtil from '@/components/common/echart/echart-util.js';
import echartDefault from '@/components/common/echart/echart-property-default.js';
import colorBoardAll from '@/common/color_board_all.js';

const { grid } = echartDefault.echart;

/* ------------------------ */
// 公共配置
/* ------------------------ */
const dfOption = {

  /* ------通用----- */
  legend: {
    _height: 25, // 假属性，用于运算grid.top
    show: true,
    pageIconSize: 12,
    padding: 5,
    itemGap: 10,
    itemWidth: 8,
    itemHeight: 2,
    textStyle: {
      padding: 1, // 有翻页时，中文文字顶部显示不全，需要加点边距
    },
    right: grid.right,
  },
  grid: {
    left: grid.left,
    right: grid.right,
    bottom: grid.bottom,
    top: grid.top,
    containLabel: false,
  },
  xAxis: {
    show: false,
    _nameWidth: 40, // 假属性，用于计算grid.right
  },
  yAxis: {
    show: false,
    _nameHeight: 30, // 假属性，用于运算grid.top
    nameGap: 20,
    axisLine: {
      show: true,
    },
  },
  tooltip: {

    // 防止tooltip被遮挡和显示不全
    extraCssText: 'z-index: 10000;',
    confine: true,
    borderWidth: 0,
  },

  /* ------主题----- */
  light: {
    legend: {
      pageIconColor: '#2f4554', // 图例翻页按钮的颜色
      pageIconInactiveColor: '#aaa', // 图例翻页按钮不激活时（即翻页到头时）的颜色
    },
    yAxis: {
      axisLine: {
        lineStyle: {
          color: colorBoardAll.yAxis.axisLine.lineStyle.color.light,
        },
      },
    },
  },
  dark: {
    legend: {
      pageIconInactiveColor: '#666',
      pageIconColor: '#bbb',
      pageTextStyle: {
        color: '#bbb',
      },
    },
    yAxis: {
      axisLine: {
        lineStyle: {
          color: colorBoardAll.yAxis.axisLine.lineStyle.color.dark,
        },
      },
    },
  },
  real: {
    legend: {
      pageIconColor: '#bbb',
      pageIconInactiveColor: '#666',
      pageTextStyle: {
        color: '#bbb',
      },
    },
    yAxis: {
      axisLine: {
        lineStyle: {
          color: colorBoardAll.yAxis.axisLine.lineStyle.color.real,
        },
      },
    },
  },
};

/* ------------------------ */
export default {
  option: dfOption,

  // 获取配置信息
  getOption(componentStyle, key = '') {
    // 获取当前颜色主题配置
    const _option = JSON.parse(JSON.stringify(this.option));
    delete _option.light;
    delete _option.dark;
    delete _option.real;
    const _option2 = JSON.parse(JSON.stringify(this.option[componentStyle]));
    let op = {};
    mergeObj(op, _option, _option2);
    if (key) {
      op = op[key];
    }
    return op;
  },

  /**
   * 合并配置
   * @param {Object} diyOption      自定义配置
   * @param {string} property       风格，配置属性
   */
  mergeOption(diyOption, property) {
    const { componentStyle, tooltip, echart, emptyName } = property;

    // 获取当前颜色主题配置
    const commonOption = this.getOption(componentStyle);
    let option = {};
    mergeObj(option, commonOption, diyOption);
    option = this.fixGridTop(option);
    option = this.fixGridRight(option);

    // 隐藏原生tooltip
    if (
      (tooltip && tooltip.isOriginVisiable === false) ||
      (tooltip && tooltip.gantt && tooltip.gantt.isOriginVisiable === false)
    ) {
      option.tooltip.showContent = false;
    }

    // 原生tooltip xss过滤
    if (option.tooltip.formatter) {
      const oFormatter = option.tooltip.formatter;
      const type = typeof oFormatter;
      if (type === 'function') {
        option.tooltip.formatter = params => {
          let html = oFormatter(params);
          html = xssValueFilter(html);
          return html;
        };
      } else if (type === 'string') {
        option.tooltip.formatter = xssValueFilter(oFormatter);
      } else {}
    }

    option = echartUtil.mergeEchartOrgOptions(option, echart, emptyName);

    // 本地
    if (window.isLocalEnv) {
      window.option = `option = ${JSON.stringify(option, null, 2)}`;
    }
    return option;
  },

  // 判断是否柱状图或者折线图
  isLineOrBar(_option) {
    // 只针对柱形图或折线图做距离修正
    const check = _option.series.some(n => n.type === 'line' || n.type === 'bar' || n.type === 'k' || n.type === 'scatter');
    return check;
  },

  // 计算grid.top
  fixGridTop(_option) {
    // 只针对柱形图或折线图做距离修正
    let check = this.isLineOrBar(_option);
    if (!check) {
      return _option;
    }

    // 图例高度
    if (
      (_option.legend && _option.legend.show && _option.legend.data && _option.legend.data.length > 0) ||
      (_option.visualMap && _option.visualMap.show)
    ) {
      _option.grid.top += _option.legend._height;
    }

    // y轴名称高度
    if (isArray(_option.yAxis)) {
      // 多y轴
      check = _option.yAxis.some(n => n.name);
      if (check) {
        _option.grid.top += this.option.yAxis._nameHeight; // 数组时用this.option
      }
    } else {
      if (_option.yAxis.name) {
        _option.grid.top += _option.yAxis._nameHeight;
      }
    }

    return _option;
  },

  // 计算grid.right
  fixGridRight(_option) {
    // 只针对柱形图或折线图做距离修正
    let check = this.isLineOrBar(_option);
    if (!check) {
      return _option;
    }

    // y轴名称高度
    if (isArray(_option.xAxis)) {
      // 多y轴
      check = _option.xAxis.some(n => n.name);
      if (check) {
        _option.grid.right += this.option.xAxis._nameWidth; // 数组时用this.option
      }
    } else {
      if (_option.xAxis.name) {
        _option.grid.right += _option.xAxis._nameWidth;
      }
    }

    return _option;
  },

  getDfColor(path, componentStyle) {
    return echartUtil.getDfColor(path, componentStyle);
  },

  // chart-option.json文件中的变量占位符替换成变量
  _parseJsonOptionVal(vars, path) {
    let val = vars;
    const _path = path.replace(/\[/g, '.[');
    const pathArr = _path.split('.');
    const len = pathArr.length;
    pathArr.forEach((k, i) => {
      let key = k;
      const arr = k.match(/\[(.*)\]/);
      if (arr) {
        // 格式如： $__echartDefault.C[`axisLineColor${componentStyle}`]
        key = arr[1];
        if (key.includes('`')) {
          key = key.replace(/\$\{(.*)\}/g, (s, s1) => vars[s1]);
          key = key.replace(/`/g, '');
        } else {
          key = vars[key];
        }
      }

      if (isObject(val) && objHas(val, key)) {
        val = val[key];
      } else if (isArray(val) && val[key] !== 'undefined') {
        val = val[key];
      } else {
        val = null;
      }
    });
    return val;
  },

  _parseJsonOptionItem(_option, i, vars) {
    const n = _option[i];
    if (typeof n === 'string' && n.startsWith('$__')) {
      const path = n.replace('$__', '');
      const val = this._parseJsonOptionVal(vars, path);
      _option[i] = val;
    }
  },

  /**
   * 将chart-option.json模板解析成option对象
   * 原来的setChartOption函数很大，需要将json提取出来，才能通过codecheck
   * @param  {object} _option 从chart-option.json加载进来的对象
   * @param  {object} vars   替换变量
   * @return {object}        替换变量后得到的对象
   */
  parseJsonOption(_option, vars) {
    if (isObject(_option)) {
      Object.entries(_option).map(([i]) => {
        this._parseJsonOptionItem(_option, i, vars);
        this.parseJsonOption(_option[i], vars);
      });
    } else if (isArray(_option)) {
      _option.forEach((n, i) => {
        this._parseJsonOptionItem(_option, i, vars);
        this.parseJsonOption(_option[i], vars);
      });
    } else {}
    return _option;
  },

  // 三个饼图的图例文字样式渲染
  formatPieLegendTextStyle( property = {}, _option = {}) {
    const { textStyle } = property.echart?.legend || {};
    if (!textStyle) {
      return _option.legend.textStyle.rich.a;
    }
    const style = getCssStyle(textStyle);
    return style;
  },

  // 三个饼图的图例数据渲染
  formatPieLegendData(data = {}, property = {}) {
    const { echart: { legend: { displayType } = {} } = {} } = property;
    const { legendData, seriesData } = data;
    if (!displayType) {
      return legendData;
    }
    const legends = [];
    const displayArr = displayType.split(',');
    seriesData.forEach(item => {
      let str = '';
      if (displayArr.includes('name')) {
        str += `${item.name}`;
      }
      if (displayArr.includes('value')) {
        str += `: ${item.trueValue}`;
      }
      if (displayArr.includes('percentage')) {
        str += `${displayArr.includes('value') ? ` (${item.percent}%)` : `: ${item.percent}%`}`;
      }
      legends.push(str);
    });
    return legends;
  },

  // 三个饼图公共方法
  formatePieLegend(name) {
    const arr = name.split(':');
    return `{a|${arr[0]}}${arr[1] ? `{a|: }{b|${arr[1]}}` : ''}`;
  },

  // 三个饼图公共方法
  convertPieData(data, property, pieType = '') {
    if (data.length) {
      // 处理没数据
      let sum = 0;
      let sumLabel = '';
      const seriesData = [];
      const legendData = [];
      const { percentDecimalCount } = property;
      for (let i = 0; i < data.length; i++) {
        const { s } = data[i]; // 类别
        let y = Number(data[i].y); // 值
        if (!objHas(data[i], 'y') || data[i].y === undefined) {
          y = 0;
        }
        sumLabel = data[i].total;
        if (isNaN(y)) {
          return -1;
        }
        sum += y; // 得验证数字

        // 单位
        let _unit = '';
        if (property.echart) {
          _unit = property.echart.series[0].label._unit || '';
        }

        const item = { value: Math.abs(y), trueValue: y, name: s, _unit };
        if (pieType === 'basic-pie') {
          item.yLabel = data[i].total;
        }

        seriesData.push({
          orgData: data[i],
          value: Math.abs(y), // 值
          trueValue: y,
          name: s,
          _unit,
        });
        legendData.push(s);
      }
      seriesData.forEach(serie => {
        if (sum > 0) {
          serie.percent = ((serie.trueValue * 100) / sum).toFixed(percentDecimalCount);
        } else {
          serie.percent = 0;
        }
      });
      return { legendData, seriesData, sum, sumLabel };
    } else {
      return null;
    }
  },

  setChartPieOption(params = {}, pieType = '') {
    const { data, property, extraConfig, tooltip, formateTooltip, setChartData, colorBoard } = params;
    let { option } = params;
    const { componentStyle } = property;
    const { originTooltipSetting } = property.tooltip || {};
    tooltip.componentStyle = componentStyle;
    tooltip.backgroundColor =
      (originTooltipSetting && originTooltipSetting.background) || colorBoard[componentStyle].tooltip.backgroundColor;
    tooltip.nameColor = colorBoard[componentStyle].tooltip.nameColor;
    tooltip.valueColor = colorBoard[componentStyle].tooltip.valueColor;
    tooltip.chartWidth = extraConfig.chartWidth || 0;

    if (pieType === 'basic-pie' || pieType === 'multidimensional-pie') {
      tooltip.bodyWidthPercent = property.bodyWidthPercent;
    }

    const vars = {
      componentStyle,
      colorBoard,
      formateTooltip,
      formateLegend: this.formatePieLegend,
      tooltip,
    };
    option = this.parseJsonOption(option, vars);

    setChartData(option, data, property);

    // 附加公共配置
    option = this.mergeOption(option, property);
    if (pieType === 'basic-pie') {
      option.grid.containLabel = true;
    }
    return option;
  },

  /**
   * 图表缩放
   */
  setDataZoom(compName, params = {}) {
    const { option: _option, data, property, colorBoard } = params;
    const xAxisData = params.xAxisData || data.xAxisData;
    const { componentStyle, barNum, barShow } = property;
    let dataZoomNum = barNum;

    if (xAxisData.length > dataZoomNum && barShow) {
      if (xAxisData.length >= dataZoomNum * 2) {
        dataZoomNum = dataZoomNum - 1;
      }
      _option.dataZoom = [
        {
          type: 'slider',
          startValue: xAxisData[0],
          end: (dataZoomNum * 100) / xAxisData.length,
          handleSize: '0%',
          moveHandleSize: 0,
          height: 4, // 滚动条高度
          bottom: 20,
          zoomLock: true,
          showDataShadow: false,
          showDetail: false,
          borderColor: 'transparent',
          backgroundColor: colorBoard[componentStyle].dataZoom.backgroundColor,
          fillerColor: colorBoard[componentStyle].dataZoom.fillerColor,
        },
      ];
    } else {
      _option.dataZoom = [];
    }
  },

  /**
   * 有yAxisName时重新调整option 样式
   */
  setYAxisName(compName, params) {
    const comps1 = [
      'common-x-multiple-y',
      'gantt-chart',
      'k-line',
      'ladder-waterfall',
      'scatter',
      'shape-chart',
      'stacked-area',
      'table-gantt-chart',
      'table-shape-chart',
      'uniaxial-bar',
      'uniaxial-line',
    ];
    const comps2 = [
      'biaxial-line-bar',
      'biaxial-line-line',
    ];
    if (comps1.includes(compName)) {
      this._setSingleYAxisName(params);
    } else if (comps2.includes(compName)) {
      this._setTwoYAxisName(params);
    } else {}
  },

  // 单轴组件y轴样式调整
  _setSingleYAxisName(params) {
    const { property, option: op, colorBoard } = params;
    const { yAxisName, componentStyle } = property;
    op.yAxis = {
      ...op.yAxis,
      name: yAxisName,
      nameTextStyle: {
        color: colorBoard[componentStyle].yAxis.axisLabel.textStyle.color,
      },
    };
  },

  // 双轴组件y轴样式调整
  _setTwoYAxisName(params) {
    const { property, option: op, colorBoard } = params;
    const { componentStyle, y0AxisName, y1AxisName } = property;
    op.yAxis[0] = {
      ...op.yAxis[0],
      name: y0AxisName,
      nameTextStyle: {
        color: colorBoard[componentStyle].yAxis.axisLabel.textStyle.color,
      },
    };
    op.yAxis[1] = {
      ...op.yAxis[1],
      name: y1AxisName,
      nameTextStyle: {
        color: colorBoard[componentStyle].yAxis.axisLabel.textStyle.color,
      },
    };
  },

  setMarkLine(compName, params) {
    const comps1 = [
      'stacked-area',
      'uniaxial-bar',
      'uniaxial-line',
    ];
    const comps2 = [
      'biaxial-line-bar',
      'biaxial-line-line',
    ];
    if (comps1.includes(compName)) {
      this._setMarkLine1(params);
    } else if (comps2.includes(compName)) {
      this._setMarkLine2(params);
    } else {}
  },

  _setMarkLine1(params) {
    const { option: _option, property, configData, colorBoard } = params;

    if (configData.hasMarkLine && configData.markLineValue) {
      const flag = isNum(configData.markLineValue);
      if (!flag) {
        return;
      }
      const { componentStyle } = property;
      _option.series[0].markLine = {
        silent: true,
        data: [
          {
            yAxis: configData.markLineValue,
            name: $demoi18n('word.referenceValue'),
          },
        ],
        symbol: ['none', 'none'],
        emphasis: {
          label: false,
        },
        label: {
          show: false,
        },
        lineStyle: {
          color: colorBoard[componentStyle].markLine.lineStyle.color,
          width: 2,
          opacity: 1,
          type: 'dotted',
        },
      };
    }
  },

  _setMarkLine2(params) {
    const { ption, property, configData, colorBoard } = params;
    if (configData.hasMarkLine && (configData.y0markLine.value || configData.y1markLine.value)) {
      const { componentStyle } = property;

      const len = option.series.length;
      const flag0 = isNum(configData.y0markLine.value);
      const flag1 = isNum(configData.y1markLine.value);

      if (flag0) {
        const _params = {
          componentStyle,
          markLine: configData.y0markLine,
          name: $demoi18n('word.left'),
          colorBoard,
        };
        option.series[0].markLine = this._setMarkLineValue(_params);
      }
      if (flag1) {
        const _params = {
          componentStyle,
          markLine: configData.y1markLine,
          name: $demoi18n('word.right'),
          colorBoard,
        };
        option.series[len - 1].markLine = this._setMarkLineValue(_params);
      }
    }
  },

  _setMarkLineValue(params) {
    const { componentStyle, markLine, name, colorBoard } = params;
    const index = name === $demoi18n('word.left') ? 0 : 1;
    return {
      silent: true,
      data: [
        {
          name: `${name}${$demoi18n('biaxial.axisRefVal')}`,
          yAxis: Number(markLine.value),
        },
      ],
      symbol: index === 0 ? ['circle', 'none'] : ['none', 'circle'],
      label: {
        show: false,
      },
      emphasis: {
        label: false,
      },
      lineStyle: {
        width: 2,
        opacity: 1,
        color: markLine.color || colorBoard[componentStyle].markLine.lineStyle[`color${index}`],
        type: 'dotted',
      },
    };
  },

  // 原生tooltip是否显示
  isOrgTooltipVisible() {
    const { tooltipIsOriginVisiable, tooltipIsVisiable, tooltipEvtType } = window.visualComp;
    if (!tooltipIsOriginVisiable) {
      return false;
    }
    if (tooltipEvtType === 'mouseover' && tooltipIsVisiable) {
      return false;
    }
    return true;
  },

  // 获取系列和x轴刻度标签数组
  getXAxisKeyAndSeriesKey(data, valueAxis = 'y') {
    const _x = valueAxis === 'x' ? 'y' : 'x';
    const seriesKey = [];
    const xAxisKey = [];
    for (let i = 0; i < data.length; i++) {
      const x = data[i][_x];
      const { s } = data[i];
      const isIncludeX_ = xAxisKey.includes(x);
      if (!isIncludeX_) {
        xAxisKey.push(x);
      }
      if (s) {
        const isIncludeS1 = seriesKey.includes(s);
        if (!isIncludeS1) {
          seriesKey.push(s);
        }
      }
    }
    return { seriesKey, xAxisKey };
  },

};
